package com.sykj.fileupload.util;

import com.sykj.fileupload.enums.FileEnum;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import javax.xml.ws.Action;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Calendar;
import java.util.UUID;

public class FileUtil {

    private static final Logger logger = LoggerFactory.getLogger(FileUtil.class);
    private static ThreadPoolUtil threadPool = ThreadPoolUtil.init();

    /**
     * 文件上传
     *
     * @param file
     * @param filePath
     * @param fileName
     * @throws IOException
     */
    public static String uploadFile(byte[] file, String filePath, String fileName) throws IOException {
        String newDir = getDirAndDateDir(fileName);
        checkPath(filePath + newDir);
        FileOutputStream out = new FileOutputStream(filePath + newDir + fileName);
        out.write(file);
        out.flush();
        out.close();
        // 压缩图片
        compressFile(new File(filePath + newDir + fileName));
        return newDir + fileName;
    }

    /**
     * 文件路径检查
     *
     * @param dirPath
     */
    public static void checkPath(String dirPath) {
        checkPath(new File(dirPath));
    }

    /**
     * 文件路径检查
     *
     * @param dirFile
     */
    public static void checkPath(File dirFile) {
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
    }

    // 物理删除；
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }


    // 逻辑删除，把文件转移到回收站
    public static String renameToUUID(String fileName) {
        return renameToUUID() + "." + fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    public static String renameToUUID() {
        return UUID.randomUUID().toString();
    }

    /**
     * 根据输入流判断是否为图片
     *
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static boolean isImage(InputStream inputStream) throws IOException {
        try {
            BufferedImage bufferedImage = ImageIO.read(inputStream);
            if (bufferedImage != null) {
                return true;
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
        return false;
    }

    /**
     * 根据文件判断是否为图片
     *
     * @param file
     * @return
     * @throws IOException
     */
    public static boolean isImage(File file) throws IOException {
        return isImage(new FileInputStream(file));
    }

    /**
     * 根据文件名判断是否为图片
     *
     * @param fileName
     * @return
     */
    public static boolean isImage(String fileName) {
        for (FileEnum fileEnum : FileEnum.values()) {
            if (fileEnum.getDir().equals("picture")) {
                if (fileEnum.getSuffix().equalsIgnoreCase(fileName.substring(fileName.lastIndexOf(".") + 1))){
                    return true;
                }
            }
        }
        return false;
    }


    public static String getDirAndDateDir(String fileName) {
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        String dir = "";
        for (FileEnum f : FileEnum.values()) {
            if (suffix.equals(f.getSuffix())) {
                dir = f.getDir();
            }
        }
        Calendar now = Calendar.getInstance();
        int year = now.get(Calendar.YEAR);
        int month = now.get(Calendar.MONTH) + 1;
        int day = now.get(Calendar.DAY_OF_MONTH);
        String dateTime = year + "-" + month + "-" + day;
        return dir + "/" + dateTime + "/";
    }


    /**
     * base64字符串解析
     *
     * @param imgBase64Str
     * @param filePath
     * @param fileName
     * @return
     */
    public static String imgBase64ToFile(String imgBase64Str, String filePath, String fileName) throws IOException {
        imgBase64Str = imgBase64Str.substring(imgBase64Str.indexOf(",") + 1);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] b = decoder.decodeBuffer(imgBase64Str);
        for (int i = 0; i < b.length; ++i) {
            if (b[i] < 0) {// 调整异常数据2w
                b[i] += 256;
            }
        }
        // 上传
        return uploadFile(b, filePath, fileName);
    }

    /**
     * 图片压缩
     *
     * @param file
     * @throws IOException
     */
    public static void compressFile(File file) throws IOException {
        compressFile(file, 0, 0);
    }

    /**
     * 根据文件处理图片
     *
     * @param imgFile
     * @param width
     * @param height
     * @throws IOException
     */
    public static void compressFile(File imgFile, int width, int height) throws IOException {
        compressFile(new FileInputStream(imgFile), imgFile.getParentFile().getAbsolutePath(), imgFile.getName(), width, height);
    }

    /**
     * 根据文件输入流处理图片
     *
     * @param inputStream
     * @param width
     * @param height
     * @throws IOException
     */
    public static void compressFile(InputStream inputStream, String filePath, String fileName, int width, int height) {
        checkPath(filePath);
        File dest = new File(filePath + File.separator + fileName);
        if (FileUtil.isImage(fileName)) {
            threadPool.executor(new Thread(() -> {
                        try {
                            // 暂停1秒，返回未压缩路径
                            Thread.sleep(1000);
                            Thumbnails.Builder<? extends InputStream> fileBuilder = Thumbnails.of(inputStream);
                            if (width == 0 || height == 0) {
                                fileBuilder.scale(1);
                            } else {
                                fileBuilder.size(width, height);
                            }
                            // 质量降低为原来80%
                            fileBuilder.outputQuality(0.8).toFile(dest);
                        } catch (Exception e) {
                            logger.error("image compress failed: " + e.getMessage());
                        } finally {
                            // 关闭流！！！
                            if (inputStream != null) {
                                try {
                                    inputStream.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    })
            );
        }
    }

}
